/**************************************************************************************************
 * red library                                                                                    *
 * Copyright © 2012 David Kretzmer                                                                *
 *                                                                                                *
 * Permission is hereby granted, free of charge, to any person obtaining a copy of this software  *
 * and associated documentation files (the "Software"), to deal in the Software without           *
 * restriction,including without limitation the rights to use, copy, modify, merge, publish,      *
 * distribute,sublicense, and/or sell copies of the Software, and to permit persons to whom the   *
 * Software is furnished to do so, subject to the following conditions:                           *
 *                                                                                                *
 * The above copyright notice and this permission notice shall be included in all copies or       *
 * substantial portions of the Software.                                                          *
 *                                                                                                *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING  *
 * BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND     *
 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,   *
 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, *
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.        *
 *                                                                                                *
 *************************************************************************************************/

#pragma once

#include "red/red.hpp"


namespace red
{
	//=============================================================================================
	//
	//=============================================================================================
	template<typename Derived, typename Column, size_t Columns>
	class static_matrix_base
	{
	public:
		typedef Derived derived_type;
		typedef Column column_type;

		static const size_t columns = Columns;
        static const size_t rows = column_type::dimension;

		typedef static_matrix_base<derived_type, column_type, columns> this_type;

		//-----------------------------------------------------------
		// Column access
		//-----------------------------------------------------------
		column_type const& column(size_t index) const
		{
			return derived().element_at(index);
		}

		column_type& column(size_t index)
		{
			return derived().element_at(index);
		}

		column_type const& operator [] (size_t index) const
		{
			return derived().element_at(index);
		}

		column_type& operator [] (size_t index)
		{
			return derived().element_at(index);
		}


		//-----------------------------------------------------------
		// Range-based for support
		//-----------------------------------------------------------
		column_type* begin() { return &column(0); }
		column_type* end() { return begin() + columns; }

		column_type const* cbegin() const { return &column(0); }
		column_type const* cend() const { return cbegin() + columns; }


		//-----------------------------------------------------------
		// Operators
		//-----------------------------------------------------------
		// +=
		static_matrix_base& operator += (static_matrix_base const &other)
		{
			for(size_t i = 0; i < columns; i++)
				column(i) += other[i];

			return *this;
		}

		// -=
		static_matrix_base& operator -= (static_matrix_base const &other)
		{
			for(size_t i = 0; i < columns; i++)
				column(i) -= other[i];

			return *this;
		}

		// *=
		static_matrix_base& operator *= (static_matrix_base const &other)
		{
			/*for(size_t col = 0; col < columns; col++)
				for(size_t row = 0; row < rows; row++)
					i) -= other[i];*/

			return *this;
		}

	private:
		derived_type const& derived() const { return static_cast<derived_type const&>(*this); }
		derived_type& derived() { return static_cast<derived_type&>(*this); }
	};

} // namespace: red
